﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.IO;
using ProjectDeployment.Loggers;

namespace ProjectDeployment.Model
{
    class Projects
    {
        public List<Project> ProjectsList { get; private set; }

        private Logger logger;

        public Projects()
        {
            LoadProjects();
            logger = Logger.instance;
        }

        private void LoadProjects()
        {
            var projectsXml = XDocument.Load("config.xml");
            var projects = from project in projectsXml.Descendants("Project")
                           select project;
            ProjectsList = new List<Project>();
            foreach (var item in projects)
            {
                Project newProject = null;

                var xElement = item.Element("ProjectType");
                if (xElement != null)
                    switch (xElement.Value)
                    {
                        case "WebService":
                            newProject = new WebService
                                              {
                                                  IsEnabled = bool.Parse(item.Element("IsEnabled").Value),
                                                  Name = item.Attribute("name").Value,
                                                  InstallerPath = item.Element("InstallerPath").Value,
                                                  InstalledPath = item.Element("InstalledPath").Value,
                                                  XmlConfiguration = item.Element("ConfigurationType"),
                                                  Parameters = item.Element("Parameters").Value
                                              };
                            break;
                    }
                ProjectsList.Add(newProject);


                if (!Directory.Exists(string.Format(Environment.CurrentDirectory + @"\{0}", newProject.Name)))
                {
                    string newPath = string.Format(Environment.CurrentDirectory + @"\{0}", newProject.Name);
                    Directory.CreateDirectory(newPath);
                    
                    foreach (var configType in newProject.XmlConfiguration.Descendants("Type").Elements("name").ToList())
                    {
                        Directory.CreateDirectory(Path.Combine(newPath, configType.Value));
                    }
                }
            }
        }

        public void InstallProjects(List<Project> projects)
        {
            if (projects.Count == 0)
            {
                logger.AddLogMessage("There are no projects loaded");
                return;
            }

            var totalProjects = projects.Count;
            var currentProjectsProcessed = 0;

            foreach (var item in projects)
            {
                if (!item.IsEnabled)
                {
                    continue;
                }

                item.PerformInstall(item.InstallerPath, item.Parameters);
                currentProjectsProcessed++;
                logger.AddLogMessage("Current progress: " + currentProjectsProcessed + "//" + totalProjects);
            }
        }

        public void UninstallProjects(List<Project> projects)
        {
            if (projects.Count == 0)
            {
                logger.AddLogMessage("There are no projects loaded");
                return;
            }

            var totalProjects = projects.Count;
            var currentProjectsProcessed = 0;

            foreach (var item in ProjectsList)
            {
                if (!item.IsEnabled)
                {
                    continue;
                }

                item.PerformUninstall(item.InstallerPath, item.Parameters);
                currentProjectsProcessed++;
                logger.AddLogMessage("Current progress: " + currentProjectsProcessed + "//" + totalProjects);
            }
        }

        public void CopyConfigFiles(List<Project> projects)
        {
            if (projects.Count == 0)
            {
                logger.AddLogMessage("There are no projects loaded");
                return;
            }

            foreach (var project in projects)
            {
                var enabledConfig = (from enabledConf in project.XmlConfiguration.Descendants("Type")
                                 let xAttribute = enabledConf.Attribute("enabled")
                                 where xAttribute != null && xAttribute.Value == "true"
                                 let attribute = enabledConf.Attribute("name")
                                 where attribute != null
                                 select attribute.Value).First();
                var sourcePath = Environment.CurrentDirectory + "\\" + project.Name + "\\" + enabledConfig;

                CopyFiles(sourcePath, project.InstalledPath);

            }
        }

        public void CopyOriginalConfigFiles(List<Project> projects)
        {
            if (projects.Count == 0)
            {
                logger.AddLogMessage("There are no projects loaded");
                return;
            }

            foreach (var project in projects)
            {
                var sourcePath = project.InstalledPath;
                var destinationPath = Environment.CurrentDirectory + "\\" + project.Name;

                logger.AddLogMessage("Copying files for project: " + project.Name);

                foreach (var configType in project.XmlConfiguration.Descendants("Type").Elements("name").ToList())
                {
                    CopyFiles(sourcePath, destinationPath + "\\" + configType.Value);
                }
                logger.AddLogMessage("Finished copying files for project: " + project.Name);
            }
        }

        private static void CopyFiles(string sourcePath, string destinationPath)
        {
            var destFile = string.Empty;

            if (Directory.Exists(sourcePath))
            {
                var directories = Directory.GetDirectories(sourcePath);
                foreach (var directory in directories)
                {
                    var directoryName = directory.Substring(directory.LastIndexOf('\\') + 1);

                    if (!Directory.Exists(Path.Combine(destinationPath, directoryName)))
                    {
                        Directory.CreateDirectory(Path.Combine(destinationPath, directoryName));
                    }
                    CopyFiles(Path.Combine(sourcePath, directoryName), Path.Combine(destinationPath, directoryName));
                }

                var files = Directory.GetFiles(sourcePath);

                foreach (var file in files)
                {
                    var filename = Path.GetFileName(file);
                    if (filename != null) destFile = Path.Combine(destinationPath, filename);
                    File.Copy(file, destFile, true);
                }
            }
            else
            {
                Console.WriteLine(@"Source Path does not exist!");
            }
        }
    }
}
